Information Hiding (and Leakage)
TL;DR
情報隠蔽は深いモジュールを作る最重要技法。インターフェースの単純化と変更の局所化をもたらす
情報漏洩は最大のレッドフラッグ。同じ知識が複数モジュールに散らばっていたら設計を見直す
時間的分解の罠に注意。「いつ実行するか」ではなく「どの知識が必要か」でモジュールを切る
深いモジュールを作るための技法に情報隠蔽(Information Hiding)がある
仕組みに関するデータ構造だったり、アルゴリズムが含まれる
2つの方法で複雑さを軽減する
インターフェースを単純化する
開発者の認知不可を減らせる
例)B木クラスを使う開発者は、木のノードの理想的な分岐数や、木のバランスをどう保つかについて心配する必要がない
システムの発展を容易にする
隠蔽すればその情報を含むモジュールの外部にはその情報への依存関係が存在しない
つまり変更範囲がそのモジュール内だけになるはず(影響範囲が少ない)
モジュールを設計する際にどのような情報を隠蔽できるか注意して考えて設計すること
より多くの情報を隠蔽できればモジュールのインターフェースも単純化できる
ただし注意がある
クラス内の変数やメソッドをprivateと宣言して隠すことは隠蔽と同じ意味ではない
クラスの外部から直接アクセスすることを不可能にするため、情報隠蔽の助けにはなり得るが、getterやsetterメソッドのようなパブリックメソッドを通じて露出する可能性がある
最良の形は、情報がモジュール内に完全に隠蔽され、モジュールの利用者にとって無関係かつ不可視である状態
でも部分的な隠蔽も価値があるよrkasu.icon
隠蔽の逆に漏洩がある
ある設計上の決定が複数のモジュールに反映されている場合に発生する
モジュール間で依存関係が生まれている状態
このとき変更をする際に複数の関係するモジュールに変更が入る
モジュールのインターフェースに現れなくても、情報は漏洩することがある
2つのクラスが特定のファイルフォーマットに関する知識ドメインを持っている
一方がRead、一方がWrtie
このときモジュール自体のインターフェースに現れていないけど実際にはその中で漏洩しているといえる
こういうとき厄介。依存していることが分かりづらいから
モジュールの情報が漏洩しているときはソフトウェア設計における最も重要なレッドフラッグの一つである
こういう場面に直面したら「特定の一つのものだけに影響するように修正するにはどうすればいいか」を自問する
色々な方法がある
影響を受けるすべてのクラスからその情報を取り出し、その情報だけをカプセル化する新しいクラスを作る
これはアプローチとしてはありえるが注意が必要
詳細を抽象化する単純なインターフェースを見つけられる場合
APIのレスポンスの値が複数のコンポーネントでPropsとして受け取るのもある意味で漏洩しているなrkasu.icon
どっかで変換した型を使ってコンポーネントはその型だけ知っている状態にする
例えばそのままfetchしたレスポンスを参照して使うと複数のコンポーネントでpropsとかで受け取るとどっちにも修正が入る
そうじゃなくてカスタムフックとかで内部的に変更があってもインターフェースとしては一緒にしておくことで漏洩を防ぐことができる
時間的分解
漏洩がよく起きる原因のひとつとして時間的分解(Temporal Decomposition)がある
操作が発生する時間的な順序によって起こってしまう
操作の実行順序が頭にあると時間的な分解の罠に陥って漏洩する可能性がある
モジュールを設計する際には、タスクが発生する順序ではなく、各タスクを遂行するために必要な知識に焦点を当てて行う
実際にHTTPプロトコルを作る講座でどうなるか
URLの文字列の読み込みとパースを別々のモジュールで行っていた
これは時間的な分解で起こった現状
もう一段階抽象化してひとつのクラスにするとよい
よくフロントエンドだと分割してテストしやすいようにするんだけど今回の件とは違った解釈で良さそうrkasu.icon
つまりここでいいたいのはexportをするときに露出に気をつけて設計して実装しろよという意味だと理解
デフォルト値(呼び出し側に不要な知識を要求してしまう)
これは本当にそのとおり
使う側に強制させるような設計はやめよう
propsとかで最小限指定しておいて後はカスタムに設定してオーバーライドなり個別設定なりを行うとよい
プライベートメソッドを、各メソッドが何らかの情報や機能をカプセル化し、クラスの残りの部分からそれを隠蔽するように設計
各インスタンス変数が使用される箇所の数を最小限にするよう努める
全部隠蔽することはできない
隠蔽しても大丈夫か。だめなものなら公開して別のアプローチで複雑さを抑える